from datetime import datetime,timedelta
from typing import  Any, Union

from jose import jwt

from app.config import secure
from app.core.base_response import UnicornException
from app.core.db.database import db
from app.core.db.redis_db import r
from app.core.error.code_total import StatusCode
from app.core.sql_compilations import SQLCompilations
from app.utils.rsa import OperateRSA
from app.utils.tools import Tools



async def login(model):
    _username = model.username
    _password = model.password
    access_id = model.access_id

    # rsa校验
    public_key = r.hget(name=access_id,key="public_key")
    if public_key:
        orsa = OperateRSA()
        reduction_username = orsa.private_b64(_username, public_key)
        reduction_password = orsa.private_b64(_password, public_key)
        # print(f"rsa解析账号：{reduction_username}")
        # print(f"rsa解析密码：{reduction_password}")
        if reduction_username and reduction_password:
            r.delete(access_id)
            user_dict = db.fetch_one(SQLCompilations.User.GET_USER,reduction_username,reduction_username,reduction_username)

            if user_dict:
                uid = user_dict.get("id")
                nickname = user_dict.get("nick_name")
                password = user_dict.get("passwd").decode("utf-8")
                # print(f"数据库存储账号：{username}")
                # print(f"数据库存储密码：{password}")

                if reduction_password == password:
                    access_token = create_token(uid)
                    return {"token":access_token,"nickname":nickname,"user_id":uid}
                else:
                    raise UnicornException(StatusCode.L30001["code"], StatusCode.L30001["msg"])
            else:
                raise UnicornException(StatusCode.L30011["code"], StatusCode.L30011["msg"])
        else:
            raise UnicornException(StatusCode.L30006["code"], StatusCode.L30006["msg"])
    else:
        raise UnicornException(StatusCode.L30012["code"], StatusCode.L30012["msg"])

def create_token(
        subject: Union[str, Any],
        expires_delda: timedelta = None
) -> str:
    """

    :param subject: token值
    :param expires_delda: 过期时间
    :return:
    """
    if expires_delda:
        expire = datetime.utcnow() + expires_delda
    else:
        expire = datetime.utcnow() + timedelta(minutes=secure.ACCESS_TOKEN_EXPIRE_MINUTES)

    to_encode = {"exp": expire, "sub": str(subject)}
    encode_jwt = jwt.encode(to_encode, secure.SECRET_KEY, algorithm=secure.ALGORITHM)
    return encode_jwt


async def generate_rsa():
    id = Tools.uid()
    public_key, private_key = OperateRSA().generate_rsa
    r.hset(id,"public_key",private_key)

    return {
        "access_id": id,
        "public_key": public_key
    }